home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / plug-ins / common / tileit.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-07-20  |  30.8 KB  |  1,250 lines

  1. /*
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This is a plug-in for the GIMP.
  5.  *
  6.  * Tileit - This plugin will take an image an make repeated
  7.  * copies of it the stepping is 1/(2**n); 1<=n<=6
  8.  *
  9.  * Copyright (C) 1997 Andy Thomas  alt@picnic.demon.co.uk
  10.  *
  11.  * This program is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 2 of the License, or
  14.  * (at your option) any later version.
  15.  *
  16.  * This program is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  *
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with this program; if not, write to the Free Software
  23.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  24.  * 
  25.  * A fair proprotion of this code was taken from the Whirl plug-in
  26.  * which was copyrighted by Federico Mena Quintero (as below).
  27.  * 
  28.  * Whirl plug-in --- distort an image into a whirlpool
  29.  * Copyright (C) 1997 Federico Mena Quintero           
  30.  *
  31.  */
  32.  
  33. /* Change log:-
  34.  * 0.2  Added new functions to allow "editing" of the tile patten.
  35.  *
  36.  * 0.1 First version released.
  37.  */
  38.  
  39. #include "config.h"
  40.  
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <signal.h>
  44. #include <string.h>
  45.  
  46. #include <gtk/gtk.h>
  47.  
  48. #include <libgimp/gimp.h>
  49. #include <libgimp/gimpui.h>
  50.  
  51. #include "libgimp/stdplugins-intl.h"
  52.  
  53.  
  54. /***** Magic numbers *****/
  55.  
  56. #define PREVIEW_SIZE 128 
  57. #define SCALE_WIDTH   80
  58. #define ENTRY_WIDTH   50
  59.  
  60. #define MAX_SEGS       6
  61.  
  62. #define PREVIEW_MASK   GDK_EXPOSURE_MASK | \
  63.                        GDK_BUTTON_PRESS_MASK | \
  64.                GDK_BUTTON_MOTION_MASK
  65.  
  66. /* Variables set in dialog box */
  67. typedef struct data
  68. {
  69.   gint numtiles;
  70. } TileItVals;
  71.  
  72. typedef struct
  73. {
  74.   GtkWidget *preview;
  75.   guchar     preview_row[PREVIEW_SIZE * 4];
  76.   gint       img_bpp;
  77.   guchar    *pv_cache;
  78.  
  79.   gint       run;
  80. } TileItInterface;
  81.  
  82. static TileItInterface tint =
  83. {
  84.   NULL,  /* Preview */
  85.   {
  86.     '4',
  87.     'u'
  88.   },     /* Preview_row */
  89.   4,     /* bpp of drawable */
  90.   NULL,
  91.   FALSE, /* run */
  92. };
  93.  
  94. static GimpDrawable *tileitdrawable;
  95. static gint       tile_width, tile_height;
  96. static GimpTile     *the_tile = NULL;
  97. static gint       img_width, img_height,img_bpp;
  98.  
  99. static void      query  (void);
  100. static void      run    (gchar    *name,
  101.              gint      nparams,
  102.              GimpParam   *param,
  103.              gint     *nreturn_vals,
  104.              GimpParam  **return_vals);
  105. /* static void      check  (GimpDrawable * drawable); */
  106.  
  107. static gint      tileit_dialog          (void);
  108.  
  109. static void      tileit_ok_callback     (GtkWidget     *widget,
  110.                      gpointer       data);
  111.  
  112. static void      tileit_scale_update    (GtkAdjustment *adjustment,
  113.                      gpointer       data);
  114.  
  115. static void      tileit_exp_update      (GtkWidget *widget, gpointer value);
  116. static void      tileit_exp_update_f    (GtkWidget *widget, gpointer value);
  117.  
  118. static void      tileit_reset           (GtkWidget *widget,
  119.                      gpointer   value);
  120. static void      tileit_radio_update    (GtkWidget *widget,
  121.                      gpointer   data);
  122. static void      tileit_hvtoggle_update (GtkWidget *widget,
  123.                      gpointer   data);
  124.  
  125. static void      do_tiles  (void);
  126. static gint      tiles_xy  (gint width, gint height,gint x,gint y,gint *nx,gint *ny);
  127. static void      all_update     (void);
  128. static void      alt_update     (void);
  129. static void      explict_update (gint);
  130.  
  131. static void      dialog_update_preview (void);
  132. static void     cache_preview         (void);
  133. static gint      tileit_preview_expose (GtkWidget *widget,
  134.                     GdkEvent  *event);
  135. static gint      tileit_preview_events (GtkWidget *widget,
  136.                     GdkEvent  *event);
  137.  
  138.  
  139. GimpPlugInInfo PLUG_IN_INFO =
  140. {
  141.   NULL,  /* init_proc  */
  142.   NULL,  /* quit_proc  */
  143.   query, /* query_proc */
  144.   run,   /* run_proc   */
  145. };
  146.  
  147. /* Values when first invoked */
  148. static TileItVals itvals =
  149. {
  150.   2
  151. };
  152.  
  153. /* Structures for call backs... */
  154. /* The "explict tile" & family */
  155. typedef enum
  156. {
  157.   ALL,
  158.   ALT,
  159.   EXPLICT
  160. } AppliedTo;
  161.  
  162. typedef struct
  163. {
  164.   AppliedTo  type;
  165.  
  166.   gint       x;        /* X - pos of tile   */
  167.   gint       y;        /* Y - pos of tile   */
  168.   GtkObject *r_adj;    /* row adjustment    */
  169.   GtkObject *c_adj;    /* column adjustment */
  170.   GtkWidget *applybut; /* The apply button  */
  171. } Exp_Call;
  172.  
  173. Exp_Call exp_call =
  174. {
  175.   ALL,
  176.   -1,
  177.   -1,
  178.   NULL,
  179.   NULL,
  180.   NULL,
  181. };
  182.  
  183. /* The reset button needs to know some toggle widgets.. */
  184.  
  185. typedef struct
  186. {
  187.   GtkWidget *htoggle;
  188.   GtkWidget *vtoggle;
  189. } Reset_Call;
  190.  
  191. Reset_Call res_call =
  192. {
  193.   NULL,
  194.   NULL,
  195. };
  196.   
  197. /* 2D - Array that holds the actions for each tile */
  198. /* Action type on cell */
  199. #define HORIZONTAL 0x1
  200. #define VERTICAL   0x2
  201.  
  202. gint tileactions[MAX_SEGS][MAX_SEGS];
  203.  
  204. /* What actions buttons toggled */
  205. static gint   do_horz = FALSE;
  206. static gint   do_vert = FALSE;
  207. static gint   opacity = 100;
  208.  
  209. /* Stuff for the preview bit */
  210. static gint   sel_x1, sel_y1, sel_x2, sel_y2;
  211. static gint   sel_width, sel_height;
  212. static gint   preview_width, preview_height;
  213. static gint   has_alpha;
  214.  
  215. MAIN ()
  216.  
  217. static void
  218. query (void)
  219. {
  220.   static GimpParamDef args[] =
  221.   {
  222.     { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
  223.     { GIMP_PDB_IMAGE, "image", "Input image (unused)" },
  224.     { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" },
  225.     { GIMP_PDB_INT32, "number_of_tiles", "Number of tiles to make" } 
  226.   };
  227.   static gint nargs = sizeof (args) / sizeof (args[0]);
  228.  
  229.   gimp_install_procedure ("plug_in_small_tiles",
  230.               "Tiles image into smaller versions of the orginal",
  231.               "More here later",
  232.               "Andy Thomas",
  233.               "Andy Thomas",
  234.               "1997",
  235.               N_("<Image>/Filters/Map/Small Tiles..."),
  236.               "RGB*, GRAY*",
  237.               GIMP_PLUGIN,
  238.               nargs, 0,
  239.               args, NULL);
  240. }
  241.  
  242. static void
  243. run (gchar    *name,
  244.      gint      nparams,
  245.      GimpParam   *param,
  246.      gint     *nreturn_vals,
  247.      GimpParam  **return_vals)
  248. {
  249.   static GimpParam values[1];
  250.   GimpDrawable *drawable;
  251.   GimpRunModeType run_mode;
  252.   GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  253.  
  254.   gint pwidth, pheight;
  255.  
  256.   run_mode = param[0].data.d_int32;
  257.  
  258.   *nreturn_vals = 1;
  259.   *return_vals = values;
  260.  
  261.   values[0].type = GIMP_PDB_STATUS;
  262.   values[0].data.d_status = status;
  263.  
  264.   tileitdrawable = drawable = gimp_drawable_get (param[2].data.d_drawable);
  265.  
  266.   img_width  = gimp_drawable_width (tileitdrawable->id);
  267.   img_height = gimp_drawable_height (tileitdrawable->id);
  268.  
  269.   has_alpha = gimp_drawable_has_alpha (tileitdrawable->id);
  270.  
  271.   tile_width  = gimp_tile_width ();
  272.   tile_height = gimp_tile_height ();
  273.  
  274.   gimp_drawable_mask_bounds (drawable->id, &sel_x1, &sel_y1, &sel_x2, &sel_y2);
  275.  
  276.   sel_width  = sel_x2 - sel_x1;
  277.   sel_height = sel_y2 - sel_y1;
  278.   
  279.   /* Calculate preview size */
  280.   
  281.   if (sel_width > sel_height)
  282.     {
  283.       pwidth  = MIN (sel_width, PREVIEW_SIZE);
  284.       pheight = sel_height * pwidth / sel_width;
  285.     }
  286.   else
  287.     {
  288.       pheight = MIN (sel_height, PREVIEW_SIZE);
  289.       pwidth  = sel_width * pheight / sel_height;
  290.     }
  291.   
  292.   preview_width  = MAX (pwidth, 2);  /* Min size is 2 */
  293.   preview_height = MAX (pheight, 2); 
  294.  
  295.   switch (run_mode)
  296.     {
  297.     case GIMP_RUN_INTERACTIVE:
  298.       INIT_I18N_UI();
  299.       gimp_get_data ("plug_in_tileit", &itvals);
  300.       if (! tileit_dialog ())
  301.     {
  302.       gimp_drawable_detach (drawable);
  303.       return;
  304.     }
  305.       break;
  306.  
  307.     case GIMP_RUN_NONINTERACTIVE:
  308.       if (nparams != 4)
  309.     {
  310.       status = GIMP_PDB_CALLING_ERROR;
  311.     }
  312.       else
  313.     {
  314.       itvals.numtiles = param[3].data.d_int32;
  315.     }
  316.       INIT_I18N();
  317.       break;
  318.  
  319.     case GIMP_RUN_WITH_LAST_VALS:
  320.       INIT_I18N();
  321.       gimp_get_data ("plug_in_tileit", &itvals);
  322.       break;
  323.  
  324.     default:
  325.       break;
  326.     }
  327.  
  328.   if (gimp_drawable_is_rgb (drawable->id) ||
  329.       gimp_drawable_is_gray (drawable->id))
  330.     {
  331.       /* Set the tile cache size */
  332.  
  333.       gimp_tile_cache_ntiles ((drawable->width + gimp_tile_width () - 1) /
  334.                   gimp_tile_width ());
  335.  
  336.       gimp_progress_init (_("Tiling..."));
  337.  
  338.       do_tiles ();
  339.    
  340.       if (run_mode != GIMP_RUN_NONINTERACTIVE)
  341.     gimp_displays_flush ();
  342.  
  343.       if (run_mode == GIMP_RUN_INTERACTIVE)
  344.     gimp_set_data ("plug_in_tileit", &itvals, sizeof (TileItVals));
  345.     }
  346.   else
  347.     {
  348.       status = GIMP_PDB_EXECUTION_ERROR;
  349.     }
  350.  
  351.   values[0].data.d_status = status;
  352.  
  353.   gimp_drawable_detach (drawable);
  354. }
  355.  
  356. /* Build the dialog up. This was the hard part! */
  357. static gint
  358. tileit_dialog (void)
  359. {
  360.   GtkWidget *dlg;
  361.   GtkWidget *main_vbox;
  362.   GtkWidget *hbox;
  363.   GtkWidget *vbox;
  364.   GtkWidget *vbox2;
  365.   GtkWidget *frame;
  366.   GtkWidget *xframe;
  367.   GtkWidget *table;
  368.   GtkWidget *sep;
  369.   GtkWidget *table2;
  370.   GtkWidget *button;
  371.   GtkWidget *label;
  372.   GtkWidget *spinbutton;
  373.   GtkObject *adj;
  374.   GtkObject *size_data;
  375.   GtkObject *op_data;
  376.   GtkWidget *toggle;
  377.   GSList  *orientation_group = NULL;
  378.  
  379.   gimp_ui_init ("tileit", TRUE);
  380.  
  381.   cache_preview (); /* Get the preview image */
  382.  
  383.   /* Start buildng the dialog up */
  384.   dlg = gimp_dialog_new ( _("TileIt"), "tileit",
  385.              gimp_standard_help_func, "filters/tileit.html",
  386.              GTK_WIN_POS_MOUSE,
  387.              FALSE, TRUE, FALSE,
  388.  
  389.              _("OK"), tileit_ok_callback,
  390.              NULL, NULL, NULL, TRUE, FALSE,
  391.              _("Cancel"), gtk_widget_destroy,
  392.              NULL, 1, NULL, FALSE, TRUE,
  393.  
  394.              NULL);
  395.  
  396.   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
  397.               GTK_SIGNAL_FUNC (gtk_main_quit),
  398.               NULL);
  399.  
  400.   main_vbox = gtk_vbox_new (FALSE, 4);
  401.   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 6);
  402.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), main_vbox,
  403.               TRUE, TRUE, 0);
  404.   gtk_widget_show (main_vbox);
  405.  
  406.   hbox = gtk_hbox_new (FALSE, 6);
  407.   gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
  408.   gtk_widget_show (hbox);
  409.  
  410.   frame = gtk_frame_new ( _("Preview"));
  411.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  412.   gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
  413.   gtk_widget_show (frame);
  414.  
  415.   vbox2 = gtk_vbox_new (TRUE, 0);
  416.   gtk_container_set_border_width (GTK_CONTAINER (vbox2), 4);
  417.   gtk_container_add (GTK_CONTAINER (frame), vbox2);
  418.   gtk_widget_show (vbox2);
  419.  
  420.   xframe = gtk_frame_new (NULL);
  421.   gtk_frame_set_shadow_type (GTK_FRAME (xframe), GTK_SHADOW_IN);
  422.   gtk_box_pack_start (GTK_BOX (vbox2), xframe, TRUE, FALSE, 0);
  423.   gtk_widget_show (xframe);
  424.  
  425.   tint.preview = gtk_preview_new (GTK_PREVIEW_COLOR);
  426.   gtk_preview_size (GTK_PREVIEW (tint.preview), preview_width, preview_height);
  427.  
  428.   gtk_widget_set_events (GTK_WIDGET (tint.preview), PREVIEW_MASK);
  429.   gtk_signal_connect_after (GTK_OBJECT (tint.preview), "expose_event",
  430.                 GTK_SIGNAL_FUNC (tileit_preview_expose),
  431.                 NULL);
  432.   gtk_signal_connect (GTK_OBJECT (tint.preview), "event",
  433.               GTK_SIGNAL_FUNC (tileit_preview_events),
  434.               NULL);
  435.  
  436.   gtk_container_add (GTK_CONTAINER (xframe), tint.preview);
  437.  
  438.   /* Area for buttons etc */
  439.  
  440.   frame = gtk_frame_new (_("Flipping"));
  441.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  442.   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
  443.   gtk_widget_show (frame);
  444.  
  445.   vbox = gtk_vbox_new (FALSE, 4);
  446.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  447.   gtk_container_add (GTK_CONTAINER (frame), vbox);
  448.   gtk_widget_show (vbox);
  449.  
  450.   hbox = gtk_hbox_new (TRUE, 4);
  451.   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  452.   gtk_widget_show (hbox);
  453.  
  454.   toggle = gtk_check_button_new_with_label (_("Horizontal"));
  455.   gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, TRUE, 0);
  456.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  457.               GTK_SIGNAL_FUNC (tileit_hvtoggle_update),
  458.               &do_horz);
  459.   gtk_widget_show (toggle);
  460.   res_call.htoggle = toggle;
  461.  
  462.   toggle = gtk_check_button_new_with_label (_("Vertical"));
  463.   gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, TRUE, 0);
  464.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  465.               GTK_SIGNAL_FUNC (tileit_hvtoggle_update),
  466.               &do_vert);
  467.   gtk_widget_show (toggle);
  468.   res_call.vtoggle = toggle;
  469.  
  470.   button = gtk_button_new_with_label (_("Reset"));
  471.   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
  472.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  473.               GTK_SIGNAL_FUNC (tileit_reset),
  474.               &res_call);
  475.   gtk_widget_show (button);
  476.  
  477.   xframe = gtk_frame_new (_("Applied to Tile"));
  478.   gtk_frame_set_shadow_type (GTK_FRAME (xframe), GTK_SHADOW_ETCHED_IN);
  479.   gtk_box_pack_start (GTK_BOX (vbox), xframe, FALSE, FALSE, 0);
  480.   gtk_widget_show (xframe);
  481.  
  482.   /* Table for the inner widgets..*/
  483.   table = gtk_table_new (6, 4, FALSE);
  484.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  485.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  486.   gtk_container_set_border_width (GTK_CONTAINER (table), 4);
  487.   gtk_container_add (GTK_CONTAINER (xframe), table);
  488.   gtk_widget_show (table);
  489.  
  490.   toggle = gtk_radio_button_new_with_label (orientation_group, _("All Tiles"));
  491.   orientation_group = gtk_radio_button_group (GTK_RADIO_BUTTON (toggle));
  492.   gtk_table_attach (GTK_TABLE (table), toggle, 0, 4, 0, 1,
  493.             GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
  494.   gtk_object_set_user_data (GTK_OBJECT (toggle), (gpointer) ALL);
  495.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  496.               GTK_SIGNAL_FUNC (tileit_radio_update),
  497.               &exp_call.type);
  498.   gtk_widget_show (toggle);
  499.  
  500.   toggle = gtk_radio_button_new_with_label (orientation_group,
  501.                         _("Alternate Tiles"));
  502.   orientation_group = gtk_radio_button_group (GTK_RADIO_BUTTON (toggle));
  503.   gtk_table_attach (GTK_TABLE (table), toggle, 0, 4, 1, 2,
  504.             GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
  505.   gtk_object_set_user_data (GTK_OBJECT (toggle), (gpointer) ALT);
  506.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  507.               GTK_SIGNAL_FUNC (tileit_radio_update),
  508.               &exp_call.type);
  509.   gtk_widget_show (toggle);
  510.  
  511.   toggle = gtk_radio_button_new_with_label (orientation_group,
  512.                                             _("Explicit Tile"));
  513.   orientation_group = gtk_radio_button_group (GTK_RADIO_BUTTON (toggle));  
  514.   gtk_table_attach (GTK_TABLE (table), toggle, 0, 1, 2, 4,
  515.             GTK_FILL | GTK_SHRINK, GTK_FILL, 0, 0);
  516.   gtk_widget_show (toggle);
  517.  
  518.   label = gtk_label_new (_("Row:"));
  519.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
  520.   gtk_table_attach (GTK_TABLE (table), label, 1, 2, 2, 3,
  521.             GTK_FILL | GTK_SHRINK , GTK_FILL, 0, 0);
  522.   gtk_widget_show (label); 
  523.  
  524.   gtk_widget_set_sensitive (label, FALSE);
  525.   gtk_object_set_data (GTK_OBJECT (toggle), "set_sensitive", label);
  526.  
  527.   spinbutton = gimp_spin_button_new (&adj, 2, 1, 6, 1, 1, 0, 1, 0);
  528.   gtk_widget_set_usize (spinbutton, ENTRY_WIDTH, -1);
  529.   gtk_table_attach (GTK_TABLE (table), spinbutton, 2, 3, 2, 3,
  530.             GTK_FILL | GTK_SHRINK, GTK_FILL, 0, 0);
  531.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  532.               GTK_SIGNAL_FUNC (tileit_exp_update_f),
  533.               &exp_call);
  534.   gtk_widget_show (spinbutton);
  535.   exp_call.r_adj = adj;
  536.  
  537.   gtk_widget_set_sensitive (spinbutton, FALSE);
  538.   gtk_object_set_data (GTK_OBJECT (label), "set_sensitive", spinbutton);
  539.  
  540.   label = gtk_label_new ( _("Column:"));
  541.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
  542.   gtk_widget_show (label); 
  543.   gtk_table_attach (GTK_TABLE (table), label, 1, 2, 3, 4,
  544.             GTK_FILL , GTK_FILL, 0, 0);
  545.  
  546.   gtk_widget_set_sensitive (label, FALSE);
  547.   gtk_object_set_data (GTK_OBJECT (spinbutton), "set_sensitive", label);
  548.  
  549.   spinbutton = gimp_spin_button_new (&adj, 2, 1, 6, 1, 1, 0, 1, 0);
  550.   gtk_widget_set_usize (spinbutton, ENTRY_WIDTH, -1);
  551.   gtk_table_attach (GTK_TABLE (table), spinbutton, 2, 3, 3, 4,
  552.             GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
  553.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  554.               GTK_SIGNAL_FUNC (tileit_exp_update_f),
  555.               &exp_call);
  556.   gtk_widget_show (spinbutton);
  557.   exp_call.c_adj = adj;
  558.  
  559.   gtk_widget_set_sensitive (spinbutton, FALSE);
  560.   gtk_object_set_data (GTK_OBJECT (label), "set_sensitive", spinbutton);
  561.  
  562.   gtk_object_set_user_data (GTK_OBJECT (toggle), (gpointer) EXPLICT);
  563.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  564.               GTK_SIGNAL_FUNC (tileit_radio_update),
  565.               &exp_call.type);
  566.  
  567.   button = gtk_button_new_with_label (_("Apply"));
  568.   gtk_table_attach (GTK_TABLE (table), button, 3, 4, 2, 4, 0, 0, 0, 0);
  569.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  570.               GTK_SIGNAL_FUNC (tileit_exp_update),
  571.               &exp_call);
  572.   gtk_widget_show (button);
  573.   exp_call.applybut = button;
  574.  
  575.   gtk_widget_set_sensitive (button, FALSE);
  576.   gtk_object_set_data (GTK_OBJECT (spinbutton), "set_sensitive", button);
  577.  
  578.   /* Widget for selecting the Opacity */
  579.   sep = gtk_hseparator_new ();
  580.   gtk_table_attach (GTK_TABLE (table), sep, 0, 4, 4, 5,
  581.             GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 1);
  582.   gtk_widget_show (sep);
  583.  
  584.   table2 = gtk_table_new (1, 3, FALSE);
  585.   gtk_table_set_col_spacings (GTK_TABLE (table2), 4);
  586.   gtk_table_attach_defaults (GTK_TABLE (table), table2, 0, 4, 5, 6);
  587.   gtk_widget_show (table2);
  588.  
  589.   op_data = gimp_scale_entry_new (GTK_TABLE (table2), 0, 0,
  590.                   _("Opacity:"), SCALE_WIDTH, ENTRY_WIDTH,
  591.                   opacity, 0, 100, 1, 10, 0,
  592.                   TRUE, 0, 0,
  593.                   NULL, NULL);
  594.   gtk_signal_connect (GTK_OBJECT (op_data), "value_changed",
  595.               GTK_SIGNAL_FUNC (tileit_scale_update),
  596.               &opacity);
  597.  
  598.   gtk_widget_show (frame); 
  599.  
  600.   /* Lower frame saying howmany segments */
  601.   frame = gtk_frame_new (_("Segment Setting"));
  602.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  603.   gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
  604.   gtk_widget_show (frame);
  605.  
  606.   table = gtk_table_new (1, 3, FALSE);
  607.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  608.   gtk_container_set_border_width (GTK_CONTAINER (table), 4);
  609.   gtk_container_add (GTK_CONTAINER (frame), table);
  610.   gtk_widget_show (table);
  611.  
  612.   gtk_widget_set_sensitive (table2, has_alpha);
  613.  
  614.   size_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
  615.                     "1 / (2 ** n)", SCALE_WIDTH, ENTRY_WIDTH,
  616.                     itvals.numtiles, 2, MAX_SEGS, 1, 1, 0,
  617.                     TRUE, 0, 0,
  618.                     NULL, NULL);
  619.   gtk_signal_connect (GTK_OBJECT (size_data), "value_changed",
  620.               GTK_SIGNAL_FUNC (tileit_scale_update),
  621.               &itvals.numtiles);
  622.  
  623.   gtk_widget_show (tint.preview);
  624.  
  625.   gtk_widget_show (dlg);
  626.   dialog_update_preview ();
  627.  
  628.   gtk_main ();
  629.   gdk_flush ();
  630.  
  631.   return tint.run;
  632. }
  633.  
  634. static void
  635. tileit_ok_callback (GtkWidget *widget,
  636.               gpointer   data)
  637. {
  638.   tint.run = TRUE;
  639.  
  640.   gtk_widget_destroy (GTK_WIDGET (data));
  641. }
  642.  
  643. static void
  644. tileit_hvtoggle_update (GtkWidget *widget,
  645.             gpointer   data)
  646. {
  647.   gimp_toggle_button_update (widget, data);
  648.  
  649.   switch (exp_call.type)
  650.     {
  651.     case ALL:
  652.       /* Clear current settings */
  653.       memset (tileactions, 0, sizeof (tileactions));
  654.       all_update ();
  655.       break;
  656.  
  657.     case ALT:
  658.       /* Clear current settings */
  659.       memset (tileactions, 0, sizeof (tileactions));
  660.       alt_update ();
  661.       break;
  662.  
  663.     case EXPLICT:
  664.       break;
  665.     }
  666.  
  667.   dialog_update_preview ();
  668. }
  669.  
  670. static void 
  671. draw_explict_sel (void)
  672. {
  673.   if (exp_call.type == EXPLICT)
  674.     {
  675.       gdouble x,y;
  676.       gdouble width  = (gdouble) preview_width / (gdouble) itvals.numtiles;
  677.       gdouble height = (gdouble) preview_height / (gdouble) itvals.numtiles;
  678.  
  679.       x = width * (exp_call.x - 1);
  680.       y = height * (exp_call.y - 1);
  681.  
  682.       gdk_gc_set_function (tint.preview->style->black_gc, GDK_INVERT);
  683.  
  684.       gdk_draw_rectangle (tint.preview->window,
  685.               tint.preview->style->black_gc,
  686.               0,
  687.               (gint) x,
  688.               (gint) y,
  689.               (gint) width,
  690.               (gint) height);
  691.       gdk_draw_rectangle (tint.preview->window,
  692.               tint.preview->style->black_gc,
  693.               0,
  694.               (gint) x + 1,
  695.               (gint) y + 1,
  696.               (gint) width - 2,
  697.               (gint) height - 2);
  698.       gdk_draw_rectangle (tint.preview->window,
  699.               tint.preview->style->black_gc,
  700.               0,
  701.               (gint) x + 2,
  702.               (gint) y + 2,
  703.               (gint) width - 4,
  704.               (gint) height - 4);
  705.  
  706.       gdk_gc_set_function (tint.preview->style->black_gc, GDK_COPY);
  707.     }
  708. }
  709.  
  710. static gint
  711. tileit_preview_expose (GtkWidget *widget,
  712.                GdkEvent  *event)
  713. {
  714.   draw_explict_sel ();
  715.  
  716.   return FALSE;
  717. }
  718.  
  719. static void
  720. exp_need_update (gint nx,
  721.          gint ny)
  722. {
  723.   if (nx <= 0 || nx > itvals.numtiles || ny <= 0 || ny > itvals.numtiles)
  724.     return;
  725.  
  726.   if( nx != exp_call.x ||
  727.       ny != exp_call.y )
  728.     {
  729.       draw_explict_sel (); /* Clear old 'un */
  730.       exp_call.x = nx;
  731.       exp_call.y = ny;
  732.       draw_explict_sel ();
  733.  
  734.       gtk_signal_handler_block_by_data (GTK_OBJECT (exp_call.c_adj), &exp_call);
  735.       gtk_signal_handler_block_by_data (GTK_OBJECT (exp_call.r_adj), &exp_call);
  736.  
  737.       gtk_adjustment_set_value (GTK_ADJUSTMENT (exp_call.c_adj), nx);
  738.       gtk_adjustment_set_value (GTK_ADJUSTMENT (exp_call.r_adj), ny);
  739.  
  740.       gtk_signal_handler_unblock_by_data (GTK_OBJECT (exp_call.c_adj),
  741.                       &exp_call);
  742.       gtk_signal_handler_unblock_by_data (GTK_OBJECT (exp_call.r_adj),
  743.                       &exp_call);
  744.     }
  745. }
  746.  
  747. static gint
  748. tileit_preview_events (GtkWidget *widget,
  749.                GdkEvent  *event)
  750. {
  751.   GdkEventButton *bevent;
  752.   GdkEventMotion *mevent;
  753.   gint nx, ny;
  754.   gint twidth  = preview_width / itvals.numtiles;
  755.   gint theight = preview_height / itvals.numtiles;
  756.  
  757.   switch (event->type)
  758.     {
  759.     case GDK_EXPOSE:
  760.       break;
  761.  
  762.     case GDK_BUTTON_PRESS:
  763.       bevent = (GdkEventButton *) event;
  764.       nx = bevent->x/twidth + 1;
  765.       ny = bevent->y/theight + 1;
  766.       exp_need_update (nx, ny);
  767.       break;
  768.  
  769.     case GDK_MOTION_NOTIFY:
  770.       mevent = (GdkEventMotion *) event;
  771.       if ( !mevent->state ) 
  772.     break;
  773.       if(mevent->x < 0 || mevent->y < 0)
  774.     break;
  775.       nx = mevent->x/twidth + 1;
  776.       ny = mevent->y/theight + 1;
  777.       exp_need_update (nx, ny);
  778.       break;
  779.  
  780.     default:
  781.       break;
  782.     }
  783.  
  784.   return FALSE;
  785. }
  786.  
  787. static void 
  788. explict_update (gint settile)
  789. {
  790.   gint x,y;
  791.  
  792.   /* Make sure bounds are OK */
  793.   y = ROUND (GTK_ADJUSTMENT (exp_call.r_adj)->value);
  794.   if (y > itvals.numtiles || y <= 0)
  795.     {
  796.       y = itvals.numtiles;
  797.     }
  798.   x = ROUND (GTK_ADJUSTMENT (exp_call.c_adj)->value);
  799.   if (x > itvals.numtiles || x <= 0)
  800.     {
  801.       x = itvals.numtiles;
  802.     }
  803.  
  804.   /* Set it */
  805.   if (settile == TRUE)
  806.     tileactions[x-1][y-1] = (((do_horz) ? HORIZONTAL : 0) |
  807.                  ((do_vert) ? VERTICAL : 0));
  808.  
  809.   exp_call.x = x;
  810.   exp_call.y = y;
  811. }
  812.  
  813. static void 
  814. all_update (void)
  815. {
  816.   gint x,y;
  817.  
  818.   for (x = 0 ; x < MAX_SEGS; x++)
  819.     for (y = 0 ; y < MAX_SEGS; y++)
  820.       tileactions[x][y] |= (((do_horz) ? HORIZONTAL : 0) |
  821.                 ((do_vert) ? VERTICAL : 0));
  822. }
  823.  
  824. static void
  825. alt_update (void)
  826. {
  827.   gint x,y;
  828.  
  829.   for (x = 0 ; x < MAX_SEGS; x++)
  830.     for (y = 0 ; y < MAX_SEGS; y++)
  831.       if (!((x + y) % 2))
  832.     tileactions[x][y] |= (((do_horz) ? HORIZONTAL : 0) |
  833.                   ((do_vert) ? VERTICAL : 0));
  834. }
  835.  
  836. static void
  837. tileit_radio_update (GtkWidget *widget,
  838.              gpointer   data)
  839. {
  840.   gimp_radio_button_update (widget, data);
  841.  
  842.   if (GTK_TOGGLE_BUTTON (widget)->active)
  843.     {
  844.       switch (exp_call.type)
  845.     {
  846.     case ALL:
  847.       /* Clear current settings */
  848.       memset (tileactions, 0, sizeof (tileactions));
  849.       all_update ();
  850.       break;
  851.  
  852.     case ALT:
  853.       /* Clear current settings */
  854.       memset (tileactions, 0, sizeof (tileactions));
  855.       alt_update ();
  856.       break;
  857.  
  858.     case EXPLICT:
  859.       explict_update (FALSE);
  860.       break;
  861.     }
  862.  
  863.       dialog_update_preview ();
  864.     }
  865. }             
  866.  
  867.  
  868. static void
  869. tileit_scale_update (GtkAdjustment *adjustment,
  870.              gpointer       data)
  871. {
  872.   gimp_int_adjustment_update (adjustment, data);
  873.  
  874.   dialog_update_preview ();
  875.  
  876. static void
  877. tileit_reset (GtkWidget *widget,
  878.           gpointer   data)
  879. {
  880.   Reset_Call *r = (Reset_Call *) data;
  881.  
  882.   memset (tileactions, 0, sizeof (tileactions));
  883.  
  884.   gtk_signal_handler_block_by_data (GTK_OBJECT (r->htoggle), &do_horz);
  885.   gtk_signal_handler_block_by_data (GTK_OBJECT (r->vtoggle), &do_vert);
  886.  
  887.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (r->htoggle), FALSE);
  888.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (r->vtoggle), FALSE);
  889.  
  890.   gtk_signal_handler_unblock_by_data (GTK_OBJECT (r->htoggle), &do_horz);
  891.   gtk_signal_handler_unblock_by_data (GTK_OBJECT (r->vtoggle), &do_vert);
  892.  
  893.   do_horz = do_vert = FALSE; 
  894.  
  895.   dialog_update_preview ();
  896.  
  897.  
  898. /* Could avoid almost dup. functions by using a field in the data 
  899.  * passed.  Must still pass the data since used in sig blocking func.
  900.  */
  901.  
  902. static void
  903. tileit_exp_update (GtkWidget *widget,
  904.            gpointer   applied)
  905. {
  906.   explict_update (TRUE);
  907.   dialog_update_preview ();
  908. }
  909.  
  910. static void
  911. tileit_exp_update_f (GtkWidget *widget,
  912.              gpointer   applied)
  913. {
  914.   explict_update (FALSE);
  915.   dialog_update_preview ();
  916. }
  917.  
  918. /* Cache the preview image - updates are a lot faster. */
  919. /* The preview_cache will contain the small image */
  920.  
  921. static void
  922. cache_preview (void)
  923. {
  924.   GimpPixelRgn src_rgn;
  925.   gint y,x;
  926.   guchar *src_rows;
  927.   guchar *p;
  928.   gint isgrey = FALSE;
  929.  
  930.   gimp_pixel_rgn_init (&src_rgn, tileitdrawable,
  931.                sel_x1, sel_y1, sel_width, sel_height, FALSE, FALSE);
  932.  
  933.   src_rows = g_new (guchar, sel_width * 4); 
  934.   p = tint.pv_cache = g_new (guchar, preview_width * preview_height * 4);
  935.  
  936.   tint.img_bpp = gimp_drawable_bpp (tileitdrawable->id);   
  937.  
  938.   if (tint.img_bpp < 3)
  939.     {
  940.       tint.img_bpp = 3 + (has_alpha ? 1 : 0);
  941.     }
  942.  
  943.   switch (gimp_drawable_type (tileitdrawable->id))
  944.     {
  945.     case GIMP_GRAYA_IMAGE:
  946.     case GIMP_GRAY_IMAGE:
  947.       isgrey = TRUE;
  948.       break;
  949.     default:
  950.       isgrey = FALSE;
  951.       break;
  952.     }
  953.  
  954.   for (y = 0; y < preview_height; y++)
  955.     {
  956.       gimp_pixel_rgn_get_row (&src_rgn,
  957.                   src_rows,
  958.                   sel_x1,
  959.                   sel_y1 + (y * sel_height) / preview_height,
  960.                   sel_width);
  961.  
  962.       for (x = 0; x < (preview_width); x ++)
  963.     {
  964.       /* Get the pixels of each col */
  965.       gint i;
  966.       for (i = 0 ; i < 3; i++)
  967.         p[x * tint.img_bpp + i] =
  968.           src_rows[((x * sel_width) / preview_width) * src_rgn.bpp +
  969.               ((isgrey) ? 0 : i)]; 
  970.       if (has_alpha)
  971.         p[x * tint.img_bpp + 3] =
  972.           src_rows[((x * sel_width) / preview_width) * src_rgn.bpp +
  973.               ((isgrey) ? 1 : 3)];
  974.     }
  975.       p += (preview_width * tint.img_bpp);
  976.     }
  977.   g_free (src_rows);
  978. }
  979.  
  980. static void
  981. tileit_get_pixel (gint    x,
  982.           gint    y,
  983.           guchar *pixel)
  984. {
  985.   static gint row  = -1;
  986.   static gint col  = -1;
  987.   
  988.   gint    newcol, newrow;
  989.   gint    newcoloff, newrowoff;
  990.   guchar *p;
  991.   int     i;
  992.   
  993.   if ((x < 0) || (x >= img_width) || (y < 0) || (y >= img_height)) {
  994.     pixel[0] = 0;
  995.     pixel[1] = 0;
  996.     pixel[2] = 0;
  997.     pixel[3] = 0;
  998.     
  999.     return;
  1000.   }
  1001.   
  1002.   newcol    = x / tile_width;
  1003.   newcoloff = x % tile_width;
  1004.   newrow    = y / tile_height;
  1005.   newrowoff = y % tile_height;
  1006.   
  1007.   if ((col != newcol) || (row != newrow) || (the_tile == NULL)) {
  1008.     if (the_tile != NULL)
  1009.       gimp_tile_unref(the_tile, FALSE);
  1010.     
  1011.     the_tile = gimp_drawable_get_tile(tileitdrawable, FALSE, newrow, newcol);
  1012.     gimp_tile_ref(the_tile);
  1013.     
  1014.     col = newcol;
  1015.     row = newrow;
  1016.   } 
  1017.   
  1018.   p = the_tile->data + the_tile->bpp * (the_tile->ewidth * newrowoff + newcoloff);
  1019.   
  1020.   for (i = img_bpp; i; i--)
  1021.     *pixel++ = *p++;
  1022. }
  1023.  
  1024.  
  1025. static void
  1026. do_tiles(void)
  1027. {
  1028.   GimpPixelRgn dest_rgn;
  1029.   gpointer  pr;
  1030.   gint      progress, max_progress;
  1031.   guchar   *dest_row;
  1032.   guchar   *dest;
  1033.   gint      row, col;
  1034.   guchar    pixel[4];
  1035.   int         nc,nr;
  1036.   int       i;
  1037.   
  1038.   /* Initialize pixel region */
  1039.   
  1040.   gimp_pixel_rgn_init(&dest_rgn, tileitdrawable, sel_x1, sel_y1, sel_width, sel_height, TRUE, TRUE);
  1041.   
  1042.   progress     = 0;
  1043.   max_progress = sel_width * sel_height;
  1044.   
  1045.   img_bpp = gimp_drawable_bpp(tileitdrawable->id);
  1046.   
  1047.   for (pr = gimp_pixel_rgns_register(1, &dest_rgn);
  1048.        pr != NULL; pr = gimp_pixel_rgns_process(pr)) {
  1049.     dest_row = dest_rgn.data;
  1050.     
  1051.     for (row = dest_rgn.y; row < (dest_rgn.y + dest_rgn.h); row++) {
  1052.       dest = dest_row;
  1053.       
  1054.       for (col = dest_rgn.x; col < (dest_rgn.x + dest_rgn.w); col++)
  1055.     {
  1056.       int an_action;
  1057.       
  1058.       an_action = 
  1059.         tiles_xy(sel_width,
  1060.              sel_height,
  1061.              col-sel_x1,row-sel_y1,
  1062.              &nc,&nr);
  1063.       tileit_get_pixel(nc+sel_x1,nr+sel_y1,pixel);
  1064.       for (i = 0; i < img_bpp; i++)
  1065.         *dest++ = pixel[i];
  1066.       
  1067.       if(an_action && has_alpha)
  1068.         {
  1069.           dest--;
  1070.           *dest = ((*dest)*opacity)/100;
  1071.           dest++;
  1072.         }
  1073.     }
  1074.       dest_row += dest_rgn.rowstride;
  1075.     } 
  1076.     
  1077.     progress += dest_rgn.w * dest_rgn.h;
  1078.     gimp_progress_update((double) progress / max_progress);
  1079.   }
  1080.   
  1081.   if (the_tile != NULL) {
  1082.     gimp_tile_unref(the_tile, FALSE);
  1083.     the_tile = NULL;
  1084.   }
  1085.   
  1086.   gimp_drawable_flush(tileitdrawable);
  1087.   gimp_drawable_merge_shadow(tileitdrawable->id, TRUE);
  1088.   gimp_drawable_update(tileitdrawable->id, sel_x1, sel_y1, sel_width, sel_height);
  1089.  
  1090.  
  1091. /* Get the xy pos and any action */
  1092. static gint
  1093. tiles_xy(gint width,
  1094.      gint height,
  1095.      gint x,
  1096.      gint y,
  1097.      gint *nx,
  1098.      gint *ny)
  1099. {
  1100.   gint px,py;
  1101.   gint rnum,cnum; 
  1102.   gint actiontype;
  1103.   gdouble rnd = 1 - (1.0/(gdouble)itvals.numtiles) +0.01;
  1104.  
  1105.   rnum = y*itvals.numtiles/height;
  1106.  
  1107.   py = (y*itvals.numtiles)%height;
  1108.   px = (x*itvals.numtiles)%width; 
  1109.   cnum = x*itvals.numtiles/width;
  1110.       
  1111.   if((actiontype = tileactions[cnum][rnum]))
  1112.     {
  1113.       if(actiontype & HORIZONTAL)
  1114.     {
  1115.       gdouble pyr;
  1116.       pyr =  height - y - 1 + rnd;
  1117.       py = ((int)(pyr*(gdouble)itvals.numtiles))%height;
  1118.     }
  1119.       
  1120.       if(actiontype & VERTICAL)
  1121.     {
  1122.       gdouble pxr;
  1123.       pxr = width - x - 1 + rnd;
  1124.       px = ((int)(pxr*(gdouble)itvals.numtiles))%width; 
  1125.     }
  1126.     }
  1127.   
  1128.   *nx = px;
  1129.   *ny = py;
  1130.  
  1131.   return(actiontype);
  1132. }
  1133.  
  1134.  
  1135. /* Given a row then srink it down a bit */
  1136. static void
  1137. do_tiles_preview(guchar *dest_row, 
  1138.         guchar *src_rows,
  1139.         gint width,
  1140.         gint dh,
  1141.         gint height,
  1142.         gint bpp)
  1143. {
  1144.   gint x;
  1145.   gint i;
  1146.   gint px,py;
  1147.   gint rnum,cnum; 
  1148.   gint actiontype;
  1149.   gdouble rnd = 1 - (1.0/(gdouble)itvals.numtiles) +0.01;
  1150.  
  1151.   rnum = dh*itvals.numtiles/height;
  1152.  
  1153.   for (x = 0; x < width; x ++) 
  1154.     {
  1155.       
  1156.       py = (dh*itvals.numtiles)%height;
  1157.       
  1158.       px = (x*itvals.numtiles)%width; 
  1159.       cnum = x*itvals.numtiles/width;
  1160.       
  1161.       if((actiontype = tileactions[cnum][rnum]))
  1162.     {
  1163.       if(actiontype & HORIZONTAL)
  1164.         {
  1165.           gdouble pyr;
  1166.           pyr =  height - dh - 1 + rnd;
  1167.           py = ((int)(pyr*(gdouble)itvals.numtiles))%height;
  1168.         }
  1169.       
  1170.       if(actiontype & VERTICAL)
  1171.         {
  1172.           gdouble pxr;
  1173.           pxr = width - x - 1 + rnd;
  1174.           px = ((int)(pxr*(gdouble)itvals.numtiles))%width; 
  1175.         }
  1176.     }
  1177.  
  1178.       for (i = 0 ; i < bpp; i++ )
  1179.     dest_row[x*tint.img_bpp+i] = 
  1180.       src_rows[(px + (py*width))*bpp+i]; 
  1181.  
  1182.       if(has_alpha && actiontype)
  1183.     dest_row[x*tint.img_bpp + (bpp - 1)] = 
  1184.       (dest_row[x*tint.img_bpp + (bpp - 1)]*opacity)/100;
  1185.  
  1186.     }
  1187. }
  1188.  
  1189. static void
  1190. dialog_update_preview (void)
  1191. {
  1192.   gint y;
  1193.   gint check, check_0, check_1;  
  1194.  
  1195.   for (y = 0; y < preview_height; y++)
  1196.     {
  1197.       if ((y / GIMP_CHECK_SIZE) & 1)
  1198.     {
  1199.       check_0 = GIMP_CHECK_DARK * 255;
  1200.       check_1 = GIMP_CHECK_LIGHT * 255;
  1201.     }
  1202.       else
  1203.     {
  1204.       check_0 = GIMP_CHECK_LIGHT * 255;
  1205.       check_1 = GIMP_CHECK_DARK * 255;
  1206.     }
  1207.  
  1208.       do_tiles_preview (tint.preview_row,
  1209.             tint.pv_cache,
  1210.             preview_width,
  1211.             y,
  1212.             preview_height,
  1213.             tint.img_bpp);
  1214.  
  1215.       if (tint.img_bpp > 3)
  1216.     {
  1217.       gint i, j;
  1218.  
  1219.       for (i = 0, j = 0 ; i < sizeof (tint.preview_row); i += 4, j += 3 )
  1220.         {
  1221.           gint alphaval;
  1222.  
  1223.           if (((i/4) / GIMP_CHECK_SIZE) & 1)
  1224.         check = check_0;
  1225.           else
  1226.         check = check_1;
  1227.  
  1228.           alphaval = tint.preview_row[i + 3];
  1229.  
  1230.           tint.preview_row[j] = 
  1231.         check + (((tint.preview_row[i] - check)*alphaval)/255);
  1232.           tint.preview_row[j + 1] = 
  1233.         check + (((tint.preview_row[i + 1] - check)*alphaval)/255);
  1234.           tint.preview_row[j + 2] = 
  1235.         check + (((tint.preview_row[i + 2] - check)*alphaval)/255);
  1236.         }
  1237.     }
  1238.  
  1239.       gtk_preview_draw_row (GTK_PREVIEW (tint.preview),
  1240.                 tint.preview_row, 0, y, preview_width);
  1241.     }
  1242.  
  1243.   draw_explict_sel ();
  1244.   gtk_widget_draw (tint.preview, NULL);
  1245.   gdk_flush ();
  1246. }
  1247.